#include "typedef.h"
#include "arm_common.h"
#include "_2arch.h"

extern executable arch_exe_ttimer;
extern executable arch_exe_tsched;
extern executable arch_irq_handler;

void arch_enable_int(int id, int cpu)
{
    gic_enable_interrupt(id, cpu);
}


void arch_set_irq_handler(executable handler)
{
    arch_irq_handler = handler;
}

static int gCoreNum;
int arch_actual_core_num()
{
    return gCoreNum;
}


/**
 * @brief Set the tick scheduler object
 *
 * @param sched_func the tick schedule function
 */
void arch_set_tick_sched(executable sched_func)
{
	arch_exe_tsched = sched_func;
}

void arch_set_ttimer_timeout(executable do_timeout)
{
    arch_exe_ttimer = do_timeout;
}

static int gCoreStatus;

static inline void core_online(int core)
{
    gCoreStatus |= (1<<core);
    asm volatile("dsb");
}

void arch_init()
{
    int core = arch_get_cpuid();
    if(core == 0)
    {
        unsigned get_scu_config();
        unsigned cfg = get_scu_config();
        unsigned num = (cfg & 0b11U) + 1;
        unsigned smp = (cfg >> 4) & 0b1111;
        kprint("cfg: %x\n", cfg);
        kprint("core recoginized: %d\n", num);
        for(int i=0; i<num; i++)
        {
            if(smp & 0b1)
                kprint("core %d join smp\n",i);
            smp = smp >> 1;
        }
        gCoreNum = num;
    }
    copy_vector();

    gicc_init();
    gicd_init();

    private_timer_init();
    set_private_timer_period(0x80000U, 0x1u);

    arch_enable_int(29, 0);
    core_online(core);
}

boolean arch_is_core_online(int core)
{
    return (gCoreStatus & (1 << core));
}
